package com.huawei.cloudapp.ui.activity;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.Toast;

import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.navigation.NavController;
import androidx.navigation.NavDestination;
import androidx.navigation.NavGraph;
import androidx.navigation.NavGraphNavigator;
import androidx.navigation.NavOptions;
import androidx.navigation.Navigation;
import androidx.navigation.Navigator;
import androidx.navigation.NavigatorProvider;
import androidx.navigation.fragment.FragmentNavigator;
import androidx.navigation.ui.NavigationUI;

import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.huawei.cloudapp.R;
import com.huawei.cloudapp.common.CASLog;
import com.huawei.cloudapp.databinding.ActivityCasCloudMainDirectBinding;
import com.huawei.cloudapp.ui.fragment.CloudPhoneFragment;
import com.huawei.cloudapp.ui.fragment.explore.ExploreFragment;
import com.huawei.cloudapp.ui.fragment.home.PhoneListFragment;
import com.huawei.cloudapp.ui.fragment.mine.MineFragment;

import java.lang.reflect.Field;
import java.util.ArrayDeque;
import java.util.List;
import java.util.Map;

public class CasCloudMainDirectActivity extends AppCompatActivity {

    private ActivityCasCloudMainDirectBinding binding;
    BottomNavigationView menuNavigation;
    private Fragment mNavHostFragment;
    private CloudPhoneFragment mCloudPhoneFragment;
    private Fragment mExploreFragment;
    private Fragment mUserFragment;
    private int storagePermission = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding = ActivityCasCloudMainDirectBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        menuNavigation = findViewById(R.id.nav_view);
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_main);
        NavigationUI.setupWithNavController(binding.navView, navController);
        mNavHostFragment = getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment_activity_main);
        setFixNavigator(navController);
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        getWindow().setStatusBarColor(Color.TRANSPARENT);

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{
                    Manifest.permission.READ_EXTERNAL_STORAGE,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE
            }, storagePermission);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == storagePermission) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                CASLog.i("storagePermission", "storagePermission");
            }
        }
    }

    @Override
    public void onBackPressed() {
        mCloudPhoneFragment = (CloudPhoneFragment) mNavHostFragment.getChildFragmentManager().getPrimaryNavigationFragment();
        if (mCloudPhoneFragment != null
                && !mCloudPhoneFragment.isHidden() && mCloudPhoneFragment.onBackPressed()) {
            return;
        }
        finish();
    }

    private void setFixNavigator(NavController navController) {
        NavigatorProvider provider = navController.getNavigatorProvider();
        //设置自定义的navigator
        FixFragmentNavigator fixFragmentNavigator =
                new FixFragmentNavigator(this, mNavHostFragment.getChildFragmentManager(), mNavHostFragment.getId());
        provider.addNavigator(fixFragmentNavigator);

        NavGraph navDestinations = initNavGraph(provider, fixFragmentNavigator);
        navController.setGraph(navDestinations);
        binding.navView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                navController.navigate(item.getItemId());
                return true;
            }
        });
    }

    private NavGraph initNavGraph(NavigatorProvider provider, FixFragmentNavigator fragmentNavigator) {
        NavGraph navGraph = new NavGraph(new NavGraphNavigator(provider));

        FragmentNavigator.Destination destination1 = fragmentNavigator.createDestination();
        destination1.setId(R.id.navigation_home);
        destination1.setClassName(PhoneListFragment.class.getCanonicalName());
        navGraph.addDestination(destination1);

        FragmentNavigator.Destination destination2 = fragmentNavigator.createDestination();
        destination2.setId(R.id.navigation_explore);
        destination2.setClassName(ExploreFragment.class.getCanonicalName());
        navGraph.addDestination(destination2);

        FragmentNavigator.Destination destination3 = fragmentNavigator.createDestination();
        destination3.setId(R.id.navigation_mine);
        destination3.setClassName(MineFragment.class.getCanonicalName());
        navGraph.addDestination(destination3);

        navGraph.setStartDestination(destination1.getId());
        return navGraph;
    }

    @Navigator.Name("fixFragment")
    public class FixFragmentNavigator extends FragmentNavigator {
        private final String TAG = "ReLoadFragmentNavigator";
        private final Context mContext;
        private final FragmentManager mFragmentManager;
        private final int mContainerId;

        public FixFragmentNavigator(@NonNull Context context, @NonNull FragmentManager manager, int containerId) {
            super(context, manager, containerId);
            mContext = context;
            mFragmentManager = manager;
            mContainerId = containerId;
        }

        @Nullable
        @Override
        public NavDestination navigate(@NonNull Destination destination, @Nullable Bundle args, @Nullable NavOptions navOptions, @Nullable Navigator.Extras navigatorExtras) {

            if (mFragmentManager.isStateSaved()) {
                Log.i(TAG, "Ignoring navigate() call: FragmentManager has already"
                        + " saved its state");
                return null;
            }
            String className = destination.getClassName();
            if (className.charAt(0) == '.') {
                className = mContext.getPackageName() + className;
            }
            Fragment frag = mFragmentManager.findFragmentByTag(className);
            if (null == frag) {
                //不存在，则创建
                frag = instantiateFragment(mContext, mFragmentManager, className, args);
            }

            frag.setArguments(args);
            final FragmentTransaction ft = mFragmentManager.beginTransaction();

            int enterAnim = navOptions != null ? navOptions.getEnterAnim() : -1;
            int exitAnim = navOptions != null ? navOptions.getExitAnim() : -1;
            int popEnterAnim = navOptions != null ? navOptions.getPopEnterAnim() : -1;
            int popExitAnim = navOptions != null ? navOptions.getPopExitAnim() : -1;
            if (enterAnim != -1 || exitAnim != -1 || popEnterAnim != -1 || popExitAnim != -1) {
                enterAnim = enterAnim != -1 ? enterAnim : 0;
                exitAnim = exitAnim != -1 ? exitAnim : 0;
                popEnterAnim = popEnterAnim != -1 ? popEnterAnim : 0;
                popExitAnim = popExitAnim != -1 ? popExitAnim : 0;
                ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim);
            }

//        ft.replace(mContainerId, frag);
            List<Fragment> fragments = mFragmentManager.getFragments();
            for (Fragment fragment : fragments) {
                ft.hide(fragment);
            }
            if (!frag.isAdded()) {
                ft.add(mContainerId, frag, className);
            }
            ft.show(frag);
            ft.setPrimaryNavigationFragment(frag);

            final @IdRes int destId = destination.getId();

            //通过反射获取mBackStack
            ArrayDeque<Integer> mBackStack;
            try {
                Field field = FragmentNavigator.class.getDeclaredField("mBackStack");
                field.setAccessible(true);
                mBackStack = (ArrayDeque<Integer>) field.get(this);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }

            final boolean initialNavigation = mBackStack.isEmpty();
            final boolean isSingleTopReplacement = navOptions != null && !initialNavigation
                    && navOptions.shouldLaunchSingleTop()
                    && mBackStack.peekLast() == destId;

            boolean isAdded;
            if (initialNavigation) {
                isAdded = true;
            } else if (isSingleTopReplacement) {
                if (mBackStack.size() > 1) {
                    mFragmentManager.popBackStack(
                            generateBackStackName(mBackStack.size(), mBackStack.peekLast()),
                            FragmentManager.POP_BACK_STACK_INCLUSIVE);
                    ft.addToBackStack(generateBackStackName(mBackStack.size(), destId));
                }
                isAdded = false;
            } else {
                ft.addToBackStack(generateBackStackName(mBackStack.size() + 1, destId));
                isAdded = true;
            }
            if (navigatorExtras instanceof Extras) {
                Extras extras = (Extras) navigatorExtras;
                for (Map.Entry<View, String> sharedElement : extras.getSharedElements().entrySet()) {
                    ft.addSharedElement(sharedElement.getKey(), sharedElement.getValue());
                }
            }
            ft.setReorderingAllowed(true);
            ft.commit();
            if (isAdded) {
                mBackStack.add(destId);
                return destination;
            } else {
                return null;
            }
        }

        @NonNull
        private String generateBackStackName(int backStackIndex, int destId) {
            return backStackIndex + "-" + destId;
        }
    }
}